module cla_adder_16 (A, B, CI, SUM, CO);
	input [15:0] A, B;
	input CI;
	output [15:0] SUM;
	output CO;

	wire C1, C2, C3;
	wire G0, P0, G1, P1, G2, P2, G3, P3;
	wire dummy1, dummy2, dummy3, dummy4;

//first
	cla_adder_4 inst(.A(A[3:0]), .B(B[3:0]), .CI(CI), .SUM(SUM[3:0]), .CO(dummy1));
	assign G0 = A[3]&B[3] | A[2]&B[2]&(A[3]^B[3]) | A[1]&B[1]&(A[2]^B[2])&(A[3]^B[3]) | A[0]&B[0]&(A[1]^B[1])&(A[2]^B[2])&(A[3]^B[3]);
	assign P0 = (A[0]^B[0]) & (A[1]^B[1]) & (A[2]^B[2]) & (A[3]^B[3]);
	assign C1 = G0 | P0&CI;

//second
	cla_adder_4 inst1(.A(A[7:4]), .B(B[7:4]), .CI(C1), .SUM(SUM[7:4]), .CO(dummy2));
	assign G1 = A[7]&B[7] | A[6]&B[6]&(A[7]^B[7]) | A[5]&B[5]&(A[6]^B[6])&(A[7]^B[7]) | A[4]&B[4]&(A[5]^B[5])&(A[6]^B[6])&(A[7]^B[7]);
	assign P1 = (A[4]^B[4]) & (A[5]^B[5]) & (A[6]^B[6]) & (A[7]^B[7]);
	assign C2 = G1 | G0&P1 | CI&P0&P1;



//third
	cla_adder_4 inst2(.A(A[11:8]), .B(B[11:8]), .CI(C2), .SUM(SUM[11:8]), .CO(dummy3));
	assign G2 = A[11]&B[11] | A[10]&B[10]&(A[11]^B[11]) | A[9]&B[9]&(A[10]^B[10])&(A[11]^B[11]) | A[8]&B[8]&(A[9]^B[9])&(A[10]^B[10])&(A[11]^B[11]);
	assign P2 = (A[8]^B[8]) & (A[9]^B[9]) & (A[10]^B[10]) & (A[11]^B[11]);
	assign C3 = G2 | G1&P2 | G0&P1&P2 | CI&P0&P1&P2;


//forth
	cla_adder_4 inst3(.A(A[15:12]), .B(B[15:12]), .CI(C3), .SUM(SUM[15:12]), .CO(dummy4));
	assign G3 = A[15]&B[15] | A[14]&B[14]&(A[15]^B[15]) | A[13]&B[13]&(A[14]^B[14])&(A[15]^B[15]) | A[12]&B[12]&(A[13]^B[13])&(A[14]^B[14])&(A[15]^B[15]);
	assign P3 = (A[12]^B[12]) & (A[13]^B[13]) & (A[14]^B[14]) & (A[15]^B[15]);
	assign CO = G3 | (G2&P2) | (G1&P2&P3) | (G0&P1&P2&P3) | (CI&P0&P1&P2&P3);


endmodule
